###########################################################################
# $Id: conceptBaseItem.p 43 2009-07-13 10:07:20Z donbeave $
###########################################################################

@CLASS
conceptBaseItem

@USE
pf/types/pfClass.p
labour/tests/labourAssert.p

@BASE
pfClass

@OPTIONS
locals

#----- Constructor -----

@create[hshData;hshOptions]
## hshOptions.classify
## hshOptions.storage
## hshOptions.storageOptions
## hshOptions.dataManager
## hshOptions.dataManagerOptions
#  ^cleanMethodArgument[hshOptions]
  $hshOptions[^hash::create[$hshOptions]]

  ^labourAssert:required[hshData;hash]

  $self._createOptions[$hshOptions]

  $self._classify[$hshOptions.classify]

  ^if($hshOptions.storage is conceptStorage){
    $self._storage[$hshOptions.storage]
  }{
     $self._storage[]
   }

  ^if($hshOptions.dataManager is conceptDataManager){
    $self._dataManager[$hshOptions.dataManager]
  }{
     $self._dataManager[]
   }

# getting all item's fields names
  $tFields[^hshData._keys[name]]

  ^pfAssert:isTrue($tFields)[Item doesn't have fields (count: ^tFields.count[]).]

  $self._fields[^hash::create[]]

# adding item's fields to this object
  ^tFields.menu{
    ^set[$tFields.name;$hshData.[$tFields.name]]
  }

  $self._isExist(false)

#----- Public -----

@factory[hshData;hshOptions]
  $result[^conceptBaseItem::create[$hshData;$hshOptions]]

@set[strName;altData]
#TODO сделать проверку на добавление только разрешенных полей
  $sMethodName[_addField_$strName]
  $jMethod[$$sMethodName]

  ^if($jMethod is junction){
    ^jMethod[$strName;$altData]
  }{
     ^_addField_DEFAULT[$strName;$altData]
   }

  $self._fields.$strName(true)

@isExist[]
  $result(^_isExist.bool(false))

@save[]
  ^_abstractMethod[]

@update[]
  ^_abstractMethod[]

@remove[]
  ^_abstractMethod[]

#----- Properties -----

@GET_STORAGE[]
  ^if(!def $self._storage){
    ^if(def $self._dataManager){
      $self._storage[$DATA_MANAGER.STORAGE]
    }{
       $self._storage[^defaultStorageFactory[$self._createOptions.storageOptions]]
     }
  }
  $result[$self._storage]

@GET_DATA_MANAGER[]
  ^if(!def $self._dataManager){
    ^if(def $self._storage){
      $self._dataManager[$STORAGE.DATA_MANAGER]
    }{
       $self._dataManager[^defaultDataManagerFactory[$self._createOptions.dataManagerOptions]]
     }
  }
  $result[$self._dataManager]

@GET_UID[]
  ^if(!def $self._UID){
    $self._UID[^math:uid64[]]
  }
  $result[$self._UID]

#----- Private -----

@_addField_DEFAULT[strName;altBody;strType]
  $oConverter[^STORAGE.getFieldConverter[$_classify;$strName]]

  ^if(def $oConverter){
    ^switch[$oConverter._type]{
      ^case[int;double;bool]{
        $self.[_$strName](^oConverter.onSelect[$altBody])
      }
      ^case[DEFAULT]{
        $self.[_$strName][^oConverter.onSelect[$altBody]]
      }
    }
  }{
     $self.[_$strName][$altBody]
   }

  ^if(!($GET_$strName is junction)){
    ^defProperty[$strName;;$strType]
  }

@_toHash[]
#TODO SortOrder должен быть number
  $result[^hash::create[]]

  ^self._fields.foreach[sName;]{
    ^if($self.$sName is int || $self.$sName is double){
      $result.$sName($self.$sName)
    }{
       $result.$sName[$self.$sName]
     }
  }

  ^if(!^isExist[]){
    $result.UID[$UID]
  }

#----- Fabriques -----

@defaultStorageFactory[hshStorageOptions]
  ^cleanMethodArgument[hshStorageOptions]
  ^use[concept/storages/conceptStorage.p]
  $result[^conceptStorage::create[$hshStorageOptions]]

@__asJSON[]
  ^use[labour/converters/labourJSON.p]
  $result[^labourJSON:encode[^_toHash[]]]